Skip to contentMethod: fireIndexedPropertyChange(String, int, int, int)
1: /*
2: * *********************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
23: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.role.ui.impl;
28:
29: import javax.annotation.Nonnull;
30: import java.beans.PropertyChangeListener;
31: import java.beans.PropertyChangeSupport;
32: import java.util.Collection;
33: import java.util.Optional;
34: import it.tidalwave.util.As;
35: import it.tidalwave.util.AsException;
36: import it.tidalwave.util.Callback;
37: import it.tidalwave.util.NamedCallback;
38: import it.tidalwave.role.ui.PresentationModel;
39: import lombok.ToString;
40: import lombok.experimental.Delegate;
41: import lombok.extern.slf4j.Slf4j;
42:
43: /***********************************************************************************************************************
44: *
45: * A default implementation of {@link PresentationModel}.
46: *
47: * @author Fabrizio Giudici
48: *
49: **********************************************************************************************************************/
50: @ToString(exclude = {"as", "pcs"}) @Slf4j
51: public class DefaultPresentationModel implements PresentationModel
52: {
53: @Nonnull
54: private final Object owner;
55:
56: @Delegate
57: private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
58:
59: private final As as;
60:
61: /*******************************************************************************************************************
62: *
63: *
64: *
65: ******************************************************************************************************************/
66: public DefaultPresentationModel (@Nonnull final Object owner, @Nonnull final Collection<Object> roles)
67: {
68: this.owner = owner;
69: as = As.forObject(owner, roles);
70: }
71:
72: /*******************************************************************************************************************
73: *
74: * {@inheritDoc}
75: *
76: ******************************************************************************************************************/
77: @Override @Nonnull
78: public <T> T as (@Nonnull final Class<T> roleType)
79: {
80: return maybeAs(roleType).orElseThrow(() -> new AsException(roleType));
81: }
82:
83: /*******************************************************************************************************************
84: *
85: * {@inheritDoc}
86: *
87: ******************************************************************************************************************/
88: @Override @Nonnull
89: public <T> Optional<T> maybeAs (@Nonnull final Class<T> roleType)
90: {
91: // Undocumented feature: for instance Zephyr needs to fire property events
92: if (roleType.equals(PropertyChangeSupport.class))
93: {
94: return Optional.of(roleType.cast(pcs));
95: }
96:
97: final Optional<T> t = as.maybeAs(roleType);
98:
99: if (t.isPresent())
100: {
101: return t;
102: }
103:
104: if (owner instanceof As)
105: {
106: try
107: {
108: final T role = ((As)owner).as(roleType);
109:
110: if (role != null) // do check it for improper implementations or partial mocks
111: {
112: return Optional.of(role);
113: }
114: }
115: catch (AsException e)
116: {
117: // fallback
118: }
119: }
120:
121: return Optional.empty();
122: }
123:
124: /*******************************************************************************************************************
125: *
126: * {@inheritDoc}
127: *
128: ******************************************************************************************************************/
129: @Override @Nonnull
130: public <T> Collection<T> asMany (@Nonnull final Class<T> roleType)
131: {
132: final Collection<T> result = as.asMany(roleType);
133:
134: // The problem here is that we want only to add local roles in owner; but calling owner.as() will also
135: // find again the global roles that were discovered by AsSupport.
136: if (roleType.isAssignableFrom(owner.getClass()))
137: {
138: result.add(roleType.cast(owner));
139: }
140:
141: if (owner instanceof As)
142: {
143: result.addAll(((As)owner).asMany(roleType));
144: }
145:
146: return result;
147: }
148:
149: /*******************************************************************************************************************
150: *
151: * {@inheritDoc}
152: *
153: ******************************************************************************************************************/
154: @Override
155: public void dispose()
156: {
157: for (final PropertyChangeListener listener : pcs.getPropertyChangeListeners().clone())
158: {
159: pcs.removePropertyChangeListener(listener);
160: }
161:
162: asMany(NamedCallback.class).stream()
163: .filter(c -> c.getName().equals(CALLBACK_DISPOSE))
164: .forEach(callback -> wrap(callback, "While calling 'dispose' callbacks"));
165: }
166:
167: /*******************************************************************************************************************
168: *
169: ******************************************************************************************************************/
170: private static void wrap (@Nonnull final Callback callback, @Nonnull final String logMessage)
171: {
172: try
173: {
174: callback.call();
175: }
176: catch (Throwable t)
177: {
178: log.error(logMessage, t);
179: }
180: }
181: }